package com.wutianyi.service;

import static com.wutianyi.entity.EntityTypeEnum.*;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.wutianyi.entity.EntityTypeEnum;

public class GeoApiServices {

	private static Cache cache;

	private static VelocityEngine velocityEngine;
	static {
		velocityEngine = new VelocityEngine();
		velocityEngine
				.setProperty("file.resource.loader.class",
						"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

		try {
			CacheFactory cacheFactory = CacheManager.getInstance()
					.getCacheFactory();
			cache = cacheFactory.createCache(Collections.EMPTY_MAP);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String getAreasByCity(String country, String province,
			String city) {
		Key cKey = KeyFactory.createKey(Country.name(), country);
		Key pKey = KeyFactory.createKey(cKey, Province.name(), province);
		Key cityKey = KeyFactory.createKey(pKey, City.name(), city);
		Query query = new Query(Area.name(), cityKey);
		List<Entity> areas = DatastoreServiceFactory.getDatastoreService()
				.prepare(query).asList(FetchOptions.Builder.withDefaults());

		return getStrings(areas, City, city, null);
	}

	public static String getCitysByProvince(String country, String province) {
		Key cKey = KeyFactory.createKey(Country.name(), country);
		Key pKey = KeyFactory.createKey(cKey, Province.name(), province);
		Query query = new Query(City.name(), pKey);
		List<Entity> citys = DatastoreServiceFactory.getDatastoreService()
				.prepare(query).asList(FetchOptions.Builder.withDefaults());
		return getStrings(citys, Province, province, null);
	}

	private static String getStrings(List<Entity> entities,
			EntityTypeEnum type, String name, Object values) {
		VelocityContext context = new VelocityContext();
		context.put("firstLevel", entities);
		context.put("root", type.name());
		context.put("values", values);
		context.put("name", name);
		Template template = velocityEngine.getTemplate("/data/geo.vm");
		StringWriter sw = new StringWriter();
		template.merge(context, sw);
		return sw.toString();
	}

	public static String getAllProvinceInformations(String country) {
		Key cKey = KeyFactory.createKey(Country.name(), country);
		Query query = new Query(Province.name(), cKey);
		List<Entity> provinces = DatastoreServiceFactory
				.getAsyncDatastoreService().prepare(query).asList(
						FetchOptions.Builder.withDefaults());
		return getStrings(provinces, Country, country, null);
	}

	public static void refreshAllGeoInformation(){
		if(cache.containsKey("country")) {
			cache.remove("country");
		}
	}
	
	/**
	 * 添加对缓存的支持
	 * 
	 * @param country
	 * @return
	 */
	public static String getAllGeoInformations(String country) {
		String value = null;
		if (cache.containsKey("country")) {
			value = (String) cache.get("country");
			return value;
		}

		Map<String, List<Entity>> values = new HashMap<String, List<Entity>>();
		Key countryKey = KeyFactory.createKey(Country.name(), country);

		Query query = new Query(countryKey);
		List<Entity> entities = DatastoreServiceFactory.getDatastoreService()
				.prepare(query).asList(FetchOptions.Builder.withDefaults());
		for (Entity entity : entities) {
			Key pKey = entity.getParent();
			if (null != pKey) {
				List<Entity> es = values.get(pKey.toString());
				if (null == es) {
					es = new ArrayList<Entity>();
					values.put(pKey.toString(), es);
				}
				es.add(entity);
			}
		}
		List<Entity> provinces = values.get(countryKey.toString());
		value = getStrings(provinces, Country, country, values);
		cache.put("country", value);
		return value;
	}

	@SuppressWarnings("unchecked")
	public static Map<String, Entity> getEntityByProvinces(String country,
			String province) {

		Key cKey = KeyFactory.createKey(Country.name(), country);
		Key pKey = KeyFactory.createKey(cKey, Province.name(), province);

		Query query = new Query(pKey);
		List<Entity> entities = DatastoreServiceFactory.getDatastoreService()
				.prepare(query).asList(FetchOptions.Builder.withDefaults());
		if (null != entities && 0 != entities.size()) {
			Map<String, Entity> values = new HashMap<String, Entity>();
			for (Entity entity : entities) {
				values.put(entity.getKey().toString(), entity);
			}
			return values;
		}
		return Collections.EMPTY_MAP;
	}
}
